const BasicLatin = {"0":6,"1":6,"2":6,"3":6,"4":6,"5":6,"6":6,"7":6,"8":6,"9":6,"~":6,"}":4,"|":2,"{":4,"z":5,"y":6,"x":5,"w":8,"u":6,"t":4,"s":5,"r":4,"q":7,"p":7,"o":6,"n":6,"m":9,"l":3,"k":6,"j":3,"i":3,"h":6,"g":7,"f":4,"e":6,"d":7,"c":5,"b":7,"a":6,"`":4,"_":5,"^":5,"]":4,"\\":4,"[":4,"Z":6,"Y":7,"X":7,"V":7,"U":8,"T":6,"S":6,"R":7,"Q":8,"P":6,"O":8,"N":8,"M":9,"L":6,"K":7,"J":5,"I":3,"H":8,"G":7,"F":6,"E":6,"C":7,"B":7,"A":7,"?":5,">":6,"=":6,"<":6,";":3,":":3,"/":4,".":3,"-":5,"+":6,"*":5,")":4,"(":4,"'":2,"&":8,"%":8,"$":6,"#":7,"\"":4,"!":3," ":3,",":3,"D":8,"v":6}
const Latin1 = {"ü":6,"û":6,"ù":6,"ø":6,"÷":6,"ö":6,"õ":6,"ô":6,"ó":6,"ò":6,"ñ":6,"ð":6,"ï":3,"î":3,"í":3,"ì":3,"ë":6,"ê":6,"é":6,"è":6,"ç":5,"æ":9,"å":6,"ä":6,"ã":6,"â":6,"á":6,"à":6,"ß":6,"Þ":6,"Ý":7,"Ü":8,"Û":8,"Ú":8,"Ù":8,"Ø":8,"×":6,"Ö":8,"Õ":8,"Ô":8,"Ó":8,"Ò":8,"Ñ":8,"Ð":8,"Ï":3,"Î":3,"Í":3,"Ì":3,"Ë":6,"Ê":6,"É":6,"Ç":7,"Æ":11,"Å":7,"Ä":7,"Ã":7,"Â":7,"Á":7,"À":7,"¿":5,"¾":8,"½":8,"¼":8,"»":6,"º":5,"¹":3,"¸":4,"·":5,"¶":6,"µ":6,"´":4,"³":4,"²":4,"±":6,"¯":4,"®":5,"¬":6,"«":6,"ª":5,"©":9,"¨":2,"§":6,"¦":2,"¥":6,"¤":6,"°":4,"È":6,"ú":6}
const LatinA = {"ū":6,"Ū":8,"ũ":6,"Ũ":8,"ŧ":4,"Ŧ":6,"ť":4,"Ť":6,"ţ":4,"Ţ":6,"š":5,"Š":6,"ş":5,"Ş":6,"ŝ":5,"Ŝ":6,"ś":5,"Ś":6,"ř":4,"Ř":7,"Ŗ":7,"ŕ":4,"Ŕ":7,"Œ":12,"ő":6,"Ő":8,"ŏ":6,"Ŏ":8,"ō":6,"Ō":8,"ŋ":6,"Ŋ":8,"ŉ":6,"ň":6,"Ň":8,"ņ":6,"Ņ":8,"ń":6,"Ń":8,"ł":3,"Ł":6,"ŀ":3,"Ŀ":6,"ľ":4,"Ľ":6,"ļ":3,"Ļ":6,"ĺ":3,"Ĺ":6,"ĸ":6,"ķ":6,"Ķ":7,"ĵ":3,"Ĵ":5,"ĳ":5,"Ĳ":8,"ı":3,"İ":3,"į":3,"Į":3,"ĭ":3,"Ĭ":3,"ī":3,"Ī":3,"ĩ":3,"Ĩ":3,"ħ":6,"Ħ":8,"Ĥ":8,"ģ":7,"Ģ":7,"ġ":7,"Ġ":7,"ğ":7,"Ğ":7,"ĝ":7,"Ĝ":7,"ě":6,"Ě":6,"ę":6,"Ę":7,"ė":6,"Ė":6,"ĕ":6,"Ĕ":6,"ē":6,"Ē":6,"đ":7,"Đ":8,"ď":7,"Ď":8,"Č":7,"ċ":5,"Ċ":7,"ĉ":5,"Ĉ":7,"ć":5,"Ć":7,"ą":6,"Ą":8,"ă":6,"Ă":7,"ā":6,"č":5,"ĥ":6,"ŗ":4}
const LatinB = {"ǹ":6,"Ǹ":8,"ǵ":7,"Ǵ":7,"ǰ":3,"ǯ":5,"ǩ":6,"Ǩ":7,"ǧ":7,"Ǧ":7,"ǥ":7,"ǣ":9,"Ǣ":11,"ǡ":6,"Ǡ":7,"ǟ":6,"Ǟ":7,"ǜ":6,"Ǜ":8,"Ǚ":8,"ǘ":6,"Ǘ":8,"ǖ":6,"Ǖ":8,"ǔ":6,"Ǔ":8,"ǒ":6,"Ǒ":8,"ǐ":3,"Ǐ":3,"ǎ":6,"ǚ":6,"ǲ":10}
const IPA = {"ɡ":7,"ə":6,"ɑ":7}
const JG = {"˙":3,"˘":5,"ˋ":4,"ˊ":4,"ˉ":4,"ˇ":5}
const Greek = {"ω":8,"ψ":8,"χ":5,"φ":8,"υ":6,"τ":5,"σ":7,"ς":5,"ρ":7,"π":6,"ο":6,"ξ":5,"ν":5,"μ":6,"λ":6,"κ":6,"ι":3,"θ":6,"η":6,"ζ":5,"δ":6,"γ":6,"β":6,"α":7,"ΰ":6,"ί":3,"ή":6,"έ":5,"ά":7,"Ϋ":7,"Ϊ":3,"Ω":8,"Ψ":8,"Χ":7,"Φ":8,"Υ":7,"Τ":6,"Σ":6,"Ρ":6,"Π":8,"Ο":8,"Ξ":7,"Μ":9,"Λ":7,"Κ":7,"Ι":3,"Θ":8,"Η":8,"Ζ":6,"Ε":6,"Δ":7,"Γ":6,"Β":7,"Α":7,"Ν":8,"ε":5}
const Cyrillic = {"ё":6,"ѐ":6,"я":6,"ю":8,"э":5,"ь":6,"ы":8,"ъ":7,"щ":9,"ш":8,"ч":6,"ц":7,"х":5,"ф":8,"у":6,"т":5,"с":5,"р":7,"п":6,"о":6,"н":6,"м":8,"л":6,"к":6,"й":6,"и":6,"з":5,"ж":8,"е":6,"д":7,"г":5,"в":6,"б":6,"а":6,"Я":7,"Э":7,"Ь":7,"Ы":9,"Ъ":8,"Щ":11,"Ш":11,"Ч":7,"Ц":8,"Ф":8,"У":7,"Т":6,"С":7,"Р":6,"П":8,"О":8,"Н":8,"М":9,"Л":8,"К":7,"Й":8,"И":8,"З":6,"Ж":11,"Е":6,"Д":8,"Г":6,"В":7,"Б":7,"А":7,"Џ":8,"Ў":7,"Ќ":7,"Ћ":9,"Њ":12,"Љ":12,"Ј":5,"Ї":3,"І":3,"Ѕ":6,"Є":7,"Ѓ":6,"Ђ":9,"Ё":6,"Ѝ":8,"Х":7}
const Generalized = {"›":4,"‹":4,"‷":6,"‶":4,"‵":2,"″":4,"′":2,"‰":12,"‧":5,"‡":6,"†":6,"„":5,"”":5,"‛":3,"‚":3,"’":3,"‘":3,"‗":5,"–":6,"‒":5,"‑":5,"‐":5,"“":5,"‴":6}
const SimilarToLetters = {"℡":13,"№":12,"ℓ":3,"℉":9,"℅":8,"ℏ":10}
const SimilarToNumber = {"ⅹ":5,"ⅸ":8,"ⅷ":13,"ⅵ":8,"ⅴ":6,"ⅳ":8,"ⅲ":8,"ⅱ":5,"ⅰ":3,"Ⅻ":12,"Ⅹ":7,"Ⅷ":15,"Ⅶ":12,"Ⅴ":7,"Ⅲ":8,"Ⅱ":6,"Ⅰ":3}
const Arrow = {"↕":13,"↔":13,"←":10}
const NumericOperations = {"≱":6,"≰":6,"≥":6,"≤":6,"≠":6,"≉":6,"≈":6,"∽":6,"∫":5,"√":8,"−":6,"∑":6,"∏":8}
const Parenthesized = {"⒄":10}
const GeometricPatterns = {"◊":6,"◀":13,"▶":13,"▫":13,"▪":13}
const CJK = {"〽":13,"〰":13,"〞":5,"〝":5,"〙":11,"〘":11,"〃":4}
const CJK_1 = {"㊙":13,"㊗":13}
const CJK_2 = {"㎲":10}

/**
 * 将字符串按行拆分成分页
 * @param str 字符串
 * @param options 配置项
 */
export const strToPages = (
  str: string,
  options: {width: number, height: number, fontSize: number, lineHeight: number, titleHeight: number}
) => {
  // 1. 计算行数
  const lineNum = Math.ceil(options.height / options.lineHeight)
  const hasTitleLineNum = Math.ceil((options.height - options.titleHeight) / options.lineHeight)
  // 2. 将字符串按换行符切割，并过滤没有内容部分
  let lines = str.split("\n").filter(line => line.trim() !== "")
  // 3. 遍历并拆分每一行，合并到新的数组中
  let newLines = []
  lines.forEach(line => {
    if (/^\s\s\s\s/.test(line)) line = line.replace(/\s\s\s\s/, "       ")
    else if (/^\s\s/.test(line)) line = line.replace(/\s\s/, "       ")
    newLines = newLines.concat(splitLine(line, options.fontSize, options.width))
    newLines.push(" ")
  })
  // 4. 根据行数，返回每页的字符串
  return linesToPages1(newLines, lineNum, hasTitleLineNum)
}


/**
 * 将多行字符串合并成分页，并删除第一行空行
 * @param lines
 * @param lineNum
 * @param hasTitleLineNum
 * @returns
 */
const linesToPages1 = (lines, lineNum, hasTitleLineNum) => {
  const pages = []
  pages.push(lines.slice(0, hasTitleLineNum-1).join("\n"))
  let j = 0
  let tempLine = []
  for (let i = hasTitleLineNum-1; i < lines.length-1; i++) {
    if (j < lineNum-1) {
      tempLine.push(lines[i])
      j++
    }
    else {
      pages.push(tempLine.join("\n"))
      if (lines[i] == " ") {
        tempLine = []
        j = 0
      }
      else {
        tempLine = [lines[i]]
        j = 1
      }
    }
  }
  if (tempLine.length)
    pages.push(tempLine.join("\n"))
  return pages
}

/**
 * 将多行字符串合并成分页
 * @param lines
 * @param lineNum
 * @param hasTitleLineNum
 * @returns
 */
const linesToPages2 = (lines, lineNum, hasTitleLineNum) => {
  const pages = []
  pages.push(lines.slice(0, hasTitleLineNum-1).join("\n"))
  for (let i = hasTitleLineNum-1; i < lines.length; i+= lineNum-1) {
    pages.push(lines.slice(i, i + lineNum-1).join("\n"))
  }
  return pages
}


/**
 * 将一行按字体与宽度拆分成多行
 * @param line
 * @param fontSize
 * @param width
 * @returns
 */
const splitLine = (line: string, fontSize: number, width: number) => {
  const result = []
  // 1. 最多允许多少个中文
  const maxCharNum = Math.floor(width / fontSize)
  // 2. 如果小于最大长度，直接返回
  if (line.length <= maxCharNum) return [line]
  // 3. 最大size
  const maxSize = maxCharNum * 10
  // 4. 遍历每个字符
  let tempStr = ""
  let tempSize = 0
  for (let i = 0; i < line.length; i++) {
    const char = line[i]
    // 2. 计算宽度
    const size = getCharSize(char)
    tempSize += size
    // 3. 判断是否超过宽度
    if (tempSize > maxSize) {


      if (/[。|？|！|，|：|”|“]/.test(char)) {
        const lastChar = tempStr[tempStr.length - 1]
        if (/[\u4e00-\u9fa5]/.test(lastChar)) {
          tempStr = tempStr.slice(0, tempStr.length - 1)
          result.push(tempStr)
          tempStr = lastChar + char
          tempSize = 20
        }
        else {
          result.push(tempStr)
          tempStr = char
          tempSize = size
        }
      }
      else {
        result.push(tempStr)
        tempStr = char
        tempSize = size
      }
    }
    else {
      tempStr += char
    }
  }
  result.push(tempStr)
  return result
}


/**
 * 获取字符的宽度
 */
export const getCharSize = (char: string) => {
  if (/\s/.test(char)) return 3
  // 中文
  if (/[\u4e00-\u9fa5]/.test(char)) {
    return 10
  }
  if (BasicLatin[char]) {
    return BasicLatin[char]
  }
  if (Latin1[char]) {
    return Latin1[char]
  }
  if (LatinA[char]) {
    return LatinA[char]
  }
  if (LatinB[char]) {
    return LatinB[char]
  }
  if (IPA[char]) {
    return IPA[char]
  }
  if (JG[char]) {
    return JG[char]
  }
  if (Greek[char]) {
    return Greek[char]
  }
  if (Cyrillic[char]) {
    return Cyrillic[char]
  }
  if (Generalized[char]) {
    return Generalized[char]
  }
  if (/\u20AC/.test(char)) {
    return 6
  }
  if (SimilarToLetters[char]) {
    return SimilarToLetters[char]
  }
  if (SimilarToNumber[char]) {
    return SimilarToNumber[char]
  }
  if (Arrow[char]) {
    return Arrow[char]
  }
  if (NumericOperations[char]) {
    return NumericOperations[char]
  }
  if (Parenthesized[char]) {
    return Parenthesized[char]
  }
  if(GeometricPatterns[char]) {
    return GeometricPatterns[char]
  }
  if( CJK[char]) {
    return CJK[char]
  }
  if(CJK_1[char]) {
    return CJK_1[char]
  }
  if(CJK_2[char]) {
    return CJK_2[char]
  }
  return 10
}